#pragma once

#include<iostream>
#include<unistd.h>
#include<queue>
#include<pthread.h>
#include<cstdlib>
#include<ctime>
#define NUM 32
using namespace std;


template<typename  T>
class BlockQueue
{
  private:
    bool isFull()
    {
      return _q.size()==_cap;
    }
    bool isEmpty()
    {
      return _q.empty();
    }

  public:
    //构造函数
    BlockQueue(int cap=NUM)
      :_cap(cap)
    {
      pthread_mutex_init(&lock,nullptr);
      pthread_cond_init(&_full,nullptr);
      pthread_cond_init(&_empty,nullptr);
    }
    void push(const T& in)
    {
      pthread_mutex_lock(&lock);
      while(isFull())
      {
        pthread_cond_wait(&_full,&lock);
      }
        _q.push(in);
        if(_q.size()>=_cap/2)
        {
          //通知其他线程
          cout<<"数据已经很多了，消费者快去处理"<<endl;
          pthread_cond_signal(&_empty);
        }
      pthread_mutex_unlock(&lock);
    }
    void pop(T& out)
    {
      pthread_mutex_lock(&lock);
      while(isEmpty())
      {
        pthread_cond_wait(&_empty,&lock);
      }
      out=_q.front();
      _q.pop();
      if(_q.size()<=_cap/2)
      {
        cout<<"消费者快消费完了，生产者快生产"<<endl;
        pthread_cond_signal(&_full);
      }
      pthread_mutex_unlock(&lock);

    }
    ~BlockQueue()
    {
      pthread_mutex_destroy(&lock);
      pthread_cond_destroy(&_full);
      pthread_cond_destroy(&_empty);
    }
  private:
    queue<T>_q;
    int _cap;
    pthread_mutex_t lock;
    pthread_cond_t _full;
    pthread_cond_t _empty;
};

